package com.pdool.room.context;

import com.alibaba.fastjson2.JSON;
import com.pdool.common.constants.Constant;
import com.pdool.common.constants.MsgId;
import com.pdool.common.dto.room.CreateRoomInfo;
import com.pdool.common.msg.fight.OtherHandCountSTC;
import com.pdool.room.enums.ActionPahseEnum;
import com.pdool.room.enums.RoomState;
import com.pdool.room.fight.*;
import com.pdool.room.fight.effect.CardFightVo;
import com.pdool.room.fight.effect.EffectFightVo;
import com.pdool.room.mgr.RoomMgr;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import java.util.*;

/**
 * 房间数据上下文
 */
@Data
@NoArgsConstructor
@Slf4j
public class RoomContext {

    private CreateRoomInfo createRoomInfo;
    private RoomState state = RoomState.INIT;
    private String roomId;
    //  roleId RoleFightInfo
    private Map<Long, RoleFightInfo> memberMap = new HashMap<>();
    //  当前轮数
    private int curRound = 0;
    //  超时时间
    private int leftSec = 0;

    private int maxRound = 4;
    //  出牌的标记
    BitSet bitSet;

    private int memberCount = 2;

    //  持续卡牌的效果
    private List<EffectFightVo> effectList = new ArrayList<>();
    //  区域效果
    private List<EffectFightVo> areaEffectList = new ArrayList<>();
    int max_sec = 30;

    public void initRoomContext(CreateRoomInfo createRoomInfo, int max_sec, int maxRound) {
        this.createRoomInfo = createRoomInfo;
        int memberCount = createRoomInfo.getFightInfoList().size();
        this.bitSet = new BitSet(memberCount);
        this.memberCount = memberCount;
        this.max_sec = max_sec;
        this.maxRound = maxRound;
    }

    public void decSec() {
        try {
            leftSec--;
            if (leftSec == 24){
                aiPutCard();
            }
            if (leftSec > 0) {
                return;
            }
            //  重置为30s
            resetLeftSec();

            endRound();
        } catch (Exception e) {
            log.error("", e);
        }
    }

    public void resetLeftSec() {
        this.leftSec = max_sec;
    }

    public void skipRound(int pos) {
        bitSet.set(pos);
        //  全部已出牌
        if (bitSet.cardinality() == memberMap.size()) {
            endRound();
        }
    }

    //  结束一轮
    private void endRound() {
        bitSet.clear();
        //  掀牌
        FightUtil.getInstance().showCard(this);

        AreaEffectUtil.getInstance().doAreaEffect(this);
        //  调用效果对象
        callEffect(getEffectList(), ActionPahseEnum.ROUND_END);
        //结算当前轮
        //  判断是不是最后一轮
        if (curRound >= maxRound) {
            FightUtil.getInstance().endFight(this);
        } else {
            startRound();
        }
    }

    public void callEffect(List<EffectFightVo> effectList, ActionPahseEnum phase) {
        Iterator<EffectFightVo> iterator = effectList.iterator();
        while (iterator.hasNext()) {
            EffectFightVo effectFightVo = iterator.next();
            try {
                if (effectFightVo.getEffectConfigVo().getActionPhase() != phase.getPhase()) {
                    continue;
                }
                boolean b = EffectUtil.getInstance().canActiveEffect(effectFightVo, this);
                if (!b) {
                    continue;
                }

                List<Object> targetSelect = TargetSelectUtil.getInstance().targetSelect(this, effectFightVo);
                EffectUtil.getInstance().doEffect(effectFightVo, targetSelect, this);
                //  翻倍的效果，只能生效一次
                if ((effectFightVo.getEffectConfigVo().getExAction() == 2 || effectFightVo.getEffectConfigVo().getExAction() == 15) && targetSelect.size() != 0) {
                    iterator.remove();
                    continue;
                }
            } catch (Exception e) {
                log.error("effect error  json: {}", JSON.toJSONString(effectFightVo));
                log.error("", e);
            }

            boolean canRemove = EffectUtil.getInstance().removeEffect(effectFightVo, this);
            if (canRemove) {
                iterator.remove();
            }
        }
    }

    public void startRound() {

        //  重置最后一个卡牌
        getMemberMap().values().forEach(e -> e.getLastCardFightVo().clear());
        resetLeftSec();
        this.curRound++;
        FightUtil.getInstance().resetTmpFight(this);
        FightUtil.getInstance().pushStartRound(this);

        // TODO 发能量
        addEnergy();
        addHandCard();
//        log.error("startRound  roomId {}   round {}", roomId, this.curRound);
        FightUtil.getInstance().activeZoneEffect(this);

    }

    private void addHandCard() {

        Collection<RoleFightInfo> values = getMemberMap().values();

        OtherHandCountSTC.Builder builder = OtherHandCountSTC.newBuilder();
//        log.error("  addHandCard   round  {} ", curRound);
        for (RoleFightInfo value : values) {
            List<CardFightVo> cardList = value.getCardList();

            for (CardFightVo cardFightVo : cardList) {
                if (!value.getHandAreaInfo().getCardList().contains(cardFightVo) && !cardFightVo.isFakeCard() && cardFightVo.isValid() && cardFightVo.getAreaId() == Constant.AREA_POOL) {
                    cardFightVo.setAreaId(Constant.AREA_HAND);
                    value.getHandAreaInfo().getCardList().add(cardFightVo);
                    List<CardFightVo> addCard = new ArrayList<>();
                    addCard.add(cardFightVo);
                    FightUtil.getInstance().pushHandCardChange(cardFightVo.getRoleId(), addCard);
                    log.error("  addHandCard   roleId  {} cardId {}", cardFightVo.getRoleId(), cardFightVo.getCardId());
                    break;
                }
            }
            OtherHandCountSTC.HandCount.Builder builder1 = OtherHandCountSTC.HandCount.newBuilder();
            builder1.setRoleId(value.getRoleId());
            builder1.setCount(value.getHandAreaInfo().getCardList().size());
            builder.addHandCount(builder1.build());
        }
        RoomMgr.getInstance().sendMsg2Room(this, MsgId.OTHER_HAND_COUNT, builder.build());
    }

    private void aiPutCard() {
        for (RoleFightInfo value : getMemberMap().values()) {
            //  机器人的话直接出牌
            if (value.getRoleId() < 0) {
                AIUtil.getInstance().aiPutCard(this, value);
            }
        }
    }


    public void addEnergy() {
        for (RoleFightInfo value : memberMap.values()) {
            //  TODO 记得去掉
//            if (value.getRoleId() > 0) {
//                value.setRoundEnergy(curRound + 10);
//            } else
            value.setRoundEnergy(curRound);
        }
    }

    public void readyFight(int pos) {
        bitSet.set(pos);
        //  全部已出牌
        if (bitSet.cardinality() == memberMap.size()) {
            bitSet.clear();
            state = RoomState.READY;
            startRound();
        }
    }
}
